package com.jp.bigimageload;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Scroller;

import androidx.annotation.Nullable;

import java.io.IOException;
import java.io.InputStream;

/**
 * @ProjectName : BigImageLoad
 * @Author : Jason
 * @Time : 2020/8/16 21:47
 * @Description : 大图长图加载
 */
public class LoadBigImageView extends View implements View.OnTouchListener
        ,GestureDetector.OnGestureListener {
    private  Rect mRect;
    private  BitmapFactory.Options mOptions;
    private  GestureDetector mGestureDetector;
    private  Context context;
    private  Scroller mScroller;
    private Matrix matrix = new Matrix();
    private Bitmap bitmap;
    private int mImageWidth;
    private int mImageHeight;
    private int mViewWidth;
    private int mViewHeight;
    private BitmapRegionDecoder mBitDecoder;
    private float mScale;


    public LoadBigImageView(Context context) {
        this(context,null);
    }

    public LoadBigImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    /**
     * 第一步
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public LoadBigImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        mRect = new Rect();
        mOptions = new BitmapFactory.Options();
        mScroller = new Scroller(context);
        mGestureDetector = new GestureDetector(context,this);
        setOnTouchListener(this);
    }

    /**
     * 第二步
     * @param inputStream
     */
    public void setLoadImage(InputStream inputStream){
        if (inputStream==null) return;
        mOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(inputStream,null,mOptions);
        mImageWidth = mOptions.outWidth;
        mImageHeight = mOptions.outHeight;
        //开启区域内存复用
        mOptions.inMutable = true;
        //解码颜色配置
        mOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        mOptions.inJustDecodeBounds = false;
        //获取区域解码器
        try {
            mBitDecoder = BitmapRegionDecoder.newInstance(inputStream,false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mViewWidth = getMeasuredWidth();
        mViewHeight = getMeasuredHeight();
        mRect.left = 0;
        mRect.top = 0;
        mRect.right = mImageWidth;
        mScale = mViewWidth / (float)mImageWidth;
        mRect.bottom = (int) (mViewHeight/mScale);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mBitDecoder==null) return;
        mOptions.inBitmap = bitmap;
        bitmap = mBitDecoder.decodeRegion(mRect,mOptions);
        matrix.setScale(mScale,mScale);
        canvas.drawBitmap(bitmap,matrix,null);
    }

    /**
     * 第六步，down事件需要返回true，代表消费此事件
     * @param motionEvent
     * @return
     */
    @Override
    public boolean onDown(MotionEvent motionEvent) {
        if (!mScroller.isFinished()){
            mScroller.forceFinished(true);
        }
        return true;
    }

    @Override
    public void onShowPress(MotionEvent motionEvent) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent motionEvent) {
        return false;
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.isFinished()) {
            return;
        }
        if (mScroller.computeScrollOffset()) {
            mRect.top = mScroller.getCurrY();
            mRect.bottom =  mRect.top +
                    ((int) (mViewHeight / mScale));
            invalidate();
        }
    }

    /**
     *  * 第七步，处理滚动，滚动时，需要动态更新mRect并重绘来保证图片对应的区域能绘制到view中
     * @param motionEvent
     * @param motionEvent1
     * @param v
     * @param v1
     * @return
     */
    @Override
    public boolean onScroll(MotionEvent motionEvent,
                            MotionEvent motionEvent1,
                            float v, float v1) {
        Log.e("test", "onScroll");
        mRect.offset(0, (int) v1);
        if (mRect.bottom>mImageHeight){
            mRect.bottom = mImageHeight;
            mRect.top = mImageHeight - (int) (mViewHeight/mScale);
        }
        if (mRect.top<0){
            mRect.top = 0;
            mRect.bottom = (int) (mViewHeight/mScale);
        }
        postInvalidate();
        return false;
    }

    @Override
    public void onLongPress(MotionEvent motionEvent) {

    }

    @Override
    public boolean onFling(MotionEvent motionEvent,
                           MotionEvent motionEvent1, float velocityX, float velocityY) {
        mScroller.fling(0,mRect.top,0,(int)-velocityY,0,0,0,
                mImageHeight-(int)(mViewHeight/mScale));
        return false;
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        return mGestureDetector.onTouchEvent(motionEvent);
    }
}
